package com.zhuoyue.web.controller;


import java.io.IOException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotBlank;

import com.zhuoyue.biz.core.api.domain.AppUserHomeRelationDO;
import com.zhuoyue.biz.core.api.domain.HomeDO;
import com.zhuoyue.biz.core.api.service.impl.HomeService;
import com.zhuoyue.common.aop.check.sms.code.lived.CheckSmsCodeLived;
import com.zhuoyue.common.aop.auth.CheckLogin;
import com.zhuoyue.common.aop.auth.User;
import com.zhuoyue.common.aop.code.SmsCode;
import com.zhuoyue.common.aop.param.Params;
import com.zhuoyue.common.aop.phone.Phone;
import com.zhuoyue.common.constant.OrgCode;

import com.zhuoyue.common.exception.ErrorType;
import com.zhuoyue.common.exception.ZyServerException;
import com.zhuoyue.common.jwt.util.JwtOperator;
import com.zhuoyue.common.utils.AesUtils;
import com.zhuoyue.common.utils.SmsTpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.constraints.Length;
import org.jetbrains.annotations.NotNull;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;


import com.zhuoyue.biz.core.api.dao.AppUserDao;
import com.zhuoyue.biz.core.api.domain.AppUserDO;
import com.zhuoyue.biz.core.api.service.AppUserService;
import com.zhuoyue.biz.core.api.service.JpushService;
import com.zhuoyue.biz.core.api.service.SmsService;
import com.zhuoyue.common.constant.ExtrasCode;
import com.zhuoyue.common.constant.MessageCode;
import com.zhuoyue.common.dto.BaseResultDTO;
import com.zhuoyue.common.dto.ControllerResult;

import static com.zhuoyue.common.utils.AesUtils.encrypt;

/**
 * @author wjming
 * @ClassName: AppUserController
 * @Description: 用户中心 用户操作接口
 * @Date 2021/4/17 12:30
 */
@RestController
@RequestMapping("/api/user")
@Validated
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AppUserController {

    private final SmsService smsService;

    private final JpushService jPushService;

    private final AppUserService appUserService;

    private final AppUserDao appUserDao;

    private final HomeService homeService;

    private final JwtOperator jwtOperator;

    private final RedisTemplate redisTemplate;

    private final RabbitTemplate rabbitTemplate;
    private static final String VERIFICATION_PHONE = "^(1[3-9])\\d{9}$";
    private static final int WX = 0;
    private static final int QQ = 1;
    private static final int APPLE = 2;
    private static final String MASTER = "0";
    private static final String CHILD = "1";
    @Value("${topic.rabbit.userLoginMessage}")
    private String userLoginMessage;

    /**
     * @Description: 获取加密手机号(仅内部使用)
     * @param: phone
     * @return: java.lang.String
     * @author:wjming
     * @Date:2021/4/17 12:24
     */
    @GetMapping("/get/encrypt")
    public String getPhone(String phone) {
        String decrypt = encrypt(phone);
        return decrypt;
    }

    /**
     * @throws IOException
     * @Description: 发送手机验证码（通过手机号码获取验证码,调试需要当前只需要查看返回的参数dataObject即可）
     * @param: phoneNumber 手机号
     * @param: organizationCode 组织编码
     * @return: com.zhuoyue.common.dto.ControllerResult
     * @author:wjming
     * @Date:2021/4/17 12:24
     */
    @GetMapping("/getSmsCode")
    public ControllerResult getSmsCode(@NotBlank(message = "手机号码不能为空") String phoneNumber,
                                       @NotBlank(message = "请求头中组织编码不能为空") @RequestHeader String organizationCode) throws IOException {

        //检查是否符合所定义的正则表达式
        if (phoneNumber.matches(VERIFICATION_PHONE)) {
            return ControllerResult.toParamFail("请到手机应用市场重新下载新版本");
        }
        //解密验证
        String decrypt;
        try {
            decrypt = AesUtils.decrypt(phoneNumber);
            if (!decrypt.matches(VERIFICATION_PHONE)) {
                return ControllerResult.toParamFail("手机号码不合法!");
            }
        } catch (Exception e) {
            return ControllerResult.toParamFail("请到手机应用市场重新下载新版本");
        }

        String s = smsService.sendSmsCode(decrypt, organizationCode);
        return ControllerResult.toReturnDataSuccess("验证码发送成功!", s);
    }

    /**
     * @Description: 通过手机号验证所发请求的验证码
     * @param: phoneNumber
     * @param: code
     * @param: organizationCode
     * @return: com.zhuoyue.common.dto.ControllerResult
     * @author:wjming
     * @Date:2021/4/17 13:42
     */
    @GetMapping("/ver/code")
    @SmsCode(requestPhoneValue = "phoneNumber")
    public ControllerResult verSmsCode(@NotBlank(message = "手机号码不能为空") String phoneNumber, @RequestParam String code,
                                       @NotBlank(message = "请求头中组织编码不能为空") @RequestHeader String organizationCode) {

        try {
            redisTemplate.opsForValue().set(SmsTpl.rdsTpl(phoneNumber, organizationCode) + "_1", "1", 5, TimeUnit.MINUTES);
        } catch (Exception e) {
            throw new ZyServerException(ErrorType.Redis_Error.getCode(), "校验信息发送失败");
        }
        return ControllerResult.toReturnMessageSuccess("验证码正确");
    }


    /**
     * APP用户注册
     *
     * @param account          账号
     * @param password         密码
     * @param openId           微信，qq,苹果快速登陆开放ID
     * @param type             快速登录类型
     * @param organizationCode 组织编码
     * @return null
     */
    @PostMapping("/register")
    @Params(requestParamsValue = "password", requestParamsName = "密码")
    /**
     * 此注解的作用是防止有人不经过短信验证码，直接进行注册
     */
    @CheckSmsCodeLived(requestPhoneValue = "account")
    public ControllerResult register(@Phone String account, @Length(min = 6, max = 20, message = "请输入6-20位字符串") String password,
                                     String openId, String type, @NotNull("推送ID不能为空") String sourceId,
                                     @RequestParam(value = "sourceType", required = false) Integer sourceTypeStr,
                                     @RequestHeader(value = "organizationCode") String organizationCode) throws Exception {


        Integer typeInt = null;
        if (!StringUtils.isEmpty(type)) {
            typeInt = Integer.parseInt(type);
        }
        //如果组织编码为空先默认是极智的用户
        if (StringUtils.isEmpty(organizationCode)) {
            organizationCode = OrgCode.ZY;
        }
        AppUserDO user = new AppUserDO();
        user.setAccount(account);
        user.setPassword(password);
        user.setSourceType(sourceTypeStr);
        user.setSourceId(sourceId);
        user.setOrganizationCode(organizationCode);
        if (typeInt != null) {
            if (typeInt == 0) {
                user.setOpenidWeiXin(openId);
                user.setOpenidQQ(null);
                user.setOpenidApple(null);
            }
            if (typeInt == 1) {
                user.setOpenidWeiXin(null);
                user.setOpenidQQ(openId);
                user.setOpenidApple(null);
            }
            if (typeInt == APPLE) {
                user.setOpenidWeiXin(null);
                user.setOpenidQQ(null);
                user.setOpenidApple(openId);
            }
        }

        AppUserDO register = appUserService.register(user, organizationCode);

        // 为本次登录生成新的token
        Map<String, Object> claims = new HashMap<>(6);
        claims.put("id", register.getId());
        claims.put("account", register.getAccount());
        claims.put("orgCode", organizationCode);
        claims.put("sourceId", sourceId);
        claims.put("sourceType", sourceTypeStr);
        String token = jwtOperator.generateToken(claims);
        register.setToken(token);
        BaseResultDTO updateTokenRes = appUserService.updateTokenById(register);
        if (updateTokenRes.isFailed()) {
            return ControllerResult.toParamFail("登陆失败");
        }

        redisTemplate.opsForValue().set(account + "_" + organizationCode, token, 7, TimeUnit.DAYS);

        return ControllerResult.toReturnDataSuccess("用户注册成功!", register);
    }


    /**
     * 用户账号登陆
     * 已测试
     * 登陆方式多样：账号密码，苹果,QQ,微信快速登陆
     *
     * @param account          账号(默认是手机号码)
     * @param password         密码(注册密码(6-20位))
     * @param sourceId         手机的推送码用于推送 （极光推送ID）
     * @param openId           快速登陆开放ID
     * @param type             快速登录类型(快速登陆类型(目前支持苹果、QQ、微信))
     * @param sourceTypeStr    推送类型 (推送的手机类型)
     * @param organizationCode 组织编码
     * @return
     */
    @PostMapping("/login")
    public ControllerResult<AppUserDO> login(String account, String password,
                                             @NotNull("推送ID不能为空") String sourceId, String openId, String type,
                                             @RequestParam(value = "sourceType", required = false) String sourceTypeStr,
                                             @RequestHeader String organizationCode) throws Exception {

        // -1 失败 0:手机号登录流程 1:微信openid登录流程 2:登录并绑定微信
        int result;

        Integer typeInt = null;
        if (!StringUtils.isEmpty(type)) {
            typeInt = Integer.parseInt(type);
        }

        int sourceType = 0;
        if (!StringUtils.isEmpty(sourceTypeStr)) {
            sourceType = Integer.parseInt(sourceTypeStr);
        }

        // 验证openid和type是否为空
        if (StringUtils.isEmpty(openId)) {
            // 验证手机和密码是否为空
            if (!StringUtils.isEmpty(account)
                    && !StringUtils.isEmpty(password)) {
                // 验证手机号码
                if (!account.matches(VERIFICATION_PHONE)) {
                    return ControllerResult.toParamFail("账号只能为手机号码!");
                }
                // 获取APPUserid
                result = 0;
            } else {
                return ControllerResult.toParamFail("登录信息不完整，无法登录!");
            }
        } else {
            if (!StringUtils.isEmpty(account)
                    && !StringUtils.isEmpty(password)) {
                // 用户需要登录并绑定微信或qq的操作
                result = 2;
            } else {
                // 微信或QQ,openid登录，或苹果方式登录
                result = 1;
            }
        }
        AppUserDO getAppUserRes = null;
        // 查询用户是否存在
        if (result == 0 || result == APPLE) {
            // 手机号登录
            AppUserDO query = new AppUserDO();
            query.setAccount(account);
            query.setPassword(password);
            query.setOrganizationCode(organizationCode);
            getAppUserRes = appUserService.getAppUserByAccountAndPassword(query);
        } else if (result == 1) {
            // openid登录
            AppUserDO queryoid = new AppUserDO();
            if (typeInt == 0) {
                queryoid.setOpenidWeiXin(openId);
                //这里写个null目的是为了防止出现意外，确保能百分之百执行
                queryoid.setOpenidQQ(null);
                queryoid.setOpenidApple(null);
                queryoid.setOrganizationCode(organizationCode);
            }
            if (typeInt == 1) {
                queryoid.setOpenidWeiXin(null);
                queryoid.setOpenidApple(null);
                queryoid.setOpenidQQ(openId);
                queryoid.setOrganizationCode(organizationCode);
            }
            if (typeInt == APPLE) {
                queryoid.setOpenidWeiXin(null);
                queryoid.setOpenidApple(openId);
                queryoid.setOpenidQQ(null);
                queryoid.setOrganizationCode(organizationCode);
            }
            getAppUserRes = appUserService.getAppUserByOpenid(queryoid);
        }

        if (result == APPLE) {
            // 1：清空其他openid 两个账号，同一个微信登录，那就要先清空这个微信在之前的账号上的绑定
            AppUserDO queryClear = new AppUserDO();
            if (typeInt == 0) {
                queryClear.setOpenidWeiXin(openId);
                queryClear.setOpenidQQ(null);
                queryClear.setOpenidApple(null);
                queryClear.setOrganizationCode(organizationCode);
            }
            if (typeInt == 1) {
                queryClear.setOpenidWeiXin(null);
                queryClear.setOpenidApple(null);
                queryClear.setOpenidQQ(openId);
                queryClear.setOrganizationCode(organizationCode);
            }
            if (typeInt == APPLE) {
                queryClear.setOpenidWeiXin(null);
                queryClear.setOpenidApple(openId);
                queryClear.setOpenidQQ(null);
                queryClear.setOrganizationCode(organizationCode);
            }


            appUserService.updateClearByOpenId(queryClear);

            // 2:修改getAppUserRes的openid为参数值
            AppUserDO queryid = new AppUserDO();
            if (typeInt == 0) {
                queryid.setOpenidWeiXin(openId);
                queryid.setOpenidQQ(null);
                queryid.setOpenidApple(null);
                queryid.setOrganizationCode(organizationCode);
            }
            if (typeInt == 1) {
                queryid.setOpenidWeiXin(null);
                queryid.setOpenidApple(null);
                queryid.setOpenidQQ(openId);
                queryid.setOrganizationCode(organizationCode);
            }
            if (typeInt == APPLE) {
                queryid.setOpenidWeiXin(null);
                queryid.setOpenidApple(openId);
                queryid.setOpenidQQ(null);
                queryid.setOrganizationCode(organizationCode);
            }
            queryid.setId(getAppUserRes.getId());
            appUserService.updateOpenIdById(queryid);

            //重新赋值给app

            if (typeInt == 0) {
                getAppUserRes.setOpenidWeiXin(openId);
                getAppUserRes.setOpenidQQ(null);
                getAppUserRes.setOpenidApple(null);
                getAppUserRes.setOrganizationCode(organizationCode);
            }
            if (typeInt == 1) {
                getAppUserRes.setOpenidWeiXin(null);
                getAppUserRes.setOpenidQQ(openId);
                getAppUserRes.setOpenidApple(null);
                getAppUserRes.setOrganizationCode(organizationCode);
            }
            if (typeInt == APPLE) {
                getAppUserRes.setOpenidWeiXin(null);
                getAppUserRes.setOpenidQQ(null);
                getAppUserRes.setOpenidApple(openId);
                getAppUserRes.setOrganizationCode(organizationCode);
            }

        }
        String oldSourceId = getAppUserRes.getSourceId();

        // 为本次登录生成新的token
        Map<String, Object> claims = new HashMap<>(6);
        claims.put("id", getAppUserRes.getId());
        claims.put("account", getAppUserRes.getAccount());
        claims.put("orgCode", organizationCode);
        claims.put("sourceId", sourceId);
        claims.put("sourceType", sourceType);
        String token = jwtOperator.generateToken(claims);
        getAppUserRes.setToken(token);
        getAppUserRes.setSourceId(sourceId);
        BaseResultDTO updateTokenRes = appUserService
                .updateTokenById(getAppUserRes);
        if (updateTokenRes.isFailed()) {
            return ControllerResult.toParamFail("登陆失败");
        }
        redisTemplate.delete(account);
        redisTemplate.delete(account + "_" + organizationCode);
        redisTemplate.opsForValue().set(getAppUserRes.getAccount() + "_" + organizationCode, token, 7, TimeUnit.DAYS);

        // 下线推送
        if (StringUtils.isNotEmpty(oldSourceId) && !oldSourceId.equals(sourceId)) {
            //推送之前先判断一下之前登录的是什么手机,如果是苹果的就需要发送两条消息，如果是安卓的只需要发送一条消息即可
            //手机系统类型 1-苹果手机 2-安卓手机
            AppUserDO sourceTypeByAccount = appUserService.getSourceTypeByAccount(getAppUserRes.getAccount(), organizationCode);
            jPushService.send(MessageCode.JPUSH_TITLE,
                    "您的账号被他人登录，请注意账号安全！", MessageCode.ACCOUNT_TYPE,
                    oldSourceId, ExtrasCode.OFFLINE, "", getAppUserRes.getId()
                            + "", sourceTypeByAccount.getSourceType() + "", organizationCode);
        }
        getAppUserRes.setSourceType(sourceType);

        BaseResultDTO upSourceType = appUserService.updateTokenById(getAppUserRes);


        if (upSourceType.isFailed()) {
            return ControllerResult.toOtherFail(updateTokenRes.getErrorDetail(), updateTokenRes.getResultCode());
        }

        claims.put("time", LocalDateTime.now());
        rabbitTemplate.convertAndSend(userLoginMessage, claims);
        return ControllerResult.toReturnDataSuccess("登录成功！", getAppUserRes);
    }


    /**
     * 验证用户登录状态
     * 已经测试
     *
     * @return
     */
    @PostMapping("/validateUserState")
    @CheckLogin
    public ControllerResult validateUserState() {
        return ControllerResult.toReturnMessageSuccess("成功");
    }

    /**
     * 用户登出
     * 去掉了原先的参数，采用token验证获取用户的account
     * 已测试
     *
     * @param request
     * @return
     */
    @PostMapping("/logout")
    @CheckLogin
    public ControllerResult logout(HttpServletRequest request) {
        User user = (User) request.getAttribute("user");
        redisTemplate.delete(user.getAccount());
        redisTemplate.delete(user.getAccount() + "_" + user.getOrgCode());
        appUserDao.updateExit(user.getId());
        return ControllerResult.toReturnMessageSuccess("退出成功");
    }


    /**
     * 重置密码
     *
     * @param account  账号
     * @param password 密码
     * @param orgCode  组织编码
     * @return
     * @throws Exception
     */
    @PutMapping("/resetPassword")
    @CheckSmsCodeLived(requestPhoneValue = "account")
    public ControllerResult resetPassword(@NotNull("手机号码不能为空") String account,
                                          @NotNull("密码不能为空") @Length(min = 6, max = 20, message = "请输入6-20为字符串") String password,
                                          @RequestHeader(value = "organizationCode") String orgCode) throws Exception {
        AppUserDO appUser = new AppUserDO();
        appUser.setAccount(account);
        appUser.setPassword(password);
        appUser.setOrganizationCode(orgCode);
        Boolean resetPasswordRes = appUserService.resetPassword(appUser);
        if (!resetPasswordRes) {
            return ControllerResult.toParamFail("密码重置失败");
        }
        return ControllerResult.toReturnMessageSuccess("密码重置成功,请重新登陆");

    }

    /**
     * 修改用户信息
     *
     * @param request
     * @param nickName 昵称
     * @param imgUrl   头像
     * @return
     */
    @PutMapping("/modify")
    @CheckLogin
    public ControllerResult modifyAppUserInfo(HttpServletRequest request, String nickName, String imgUrl, String gender) {
        User user = (User) request.getAttribute("user");

        if (StringUtils.isEmpty(nickName) && StringUtils.isEmpty(imgUrl)) {
            throw new ZyServerException(ErrorType.OBJECT_NOT_FOUND);
        }
        AppUserDO appUser = new AppUserDO();
        appUser.setId(user.getId());
        appUser.setGender(gender);
        appUser.setNickName(StringUtils.isNotEmpty(nickName) ? nickName : null);
        appUser.setImgUrl(StringUtils.isNotEmpty(imgUrl) ? imgUrl : null);
        appUserService.modifyAppUserInfo(appUser);
        return ControllerResult.toReturnDataSuccess("用户信息修改成功!", appUserService.getById(user.getId()));
    }


    /***
     * 把家庭分享给子账号
     * @param request 用户信息
     * @param homeId 用户的家庭ID
     * @param childAccount 被分享者的ID
     * @return
     */
    @PostMapping(value = "/addChildUser")
    @CheckLogin
    @SmsCode(requestPhoneValue = "childAccount")
    public ControllerResult createChildAccount(HttpServletRequest request, String homeId,
                                               String childAccount) throws Exception {
        User user = (User) request.getAttribute("user");
        String organizationCode = user.getOrgCode();

        // 账号校验 自己不能给自己分享
        if (childAccount.equals(user.getAccount())) {
            return ControllerResult.toParamFail("子账号不能是登录账号！");
        }

        appUserService.createChildAccount(user.getId(), homeId, childAccount, organizationCode);
        // 通过家庭id获得家庭名称
        HomeDO homeName = homeService.getById(homeId);

        // 通过appUserid获得昵称
        AppUserDO startUser = appUserService.getById(user.getId());

        // 通过手机号获得登录的sourceId
        AppUserDO child = appUserService.getSourceTypeByAccount(childAccount, user.getOrgCode());
        // 推送
        jPushService.send(MessageCode.JPUSH_TITLE, startUser.getNickName()
                        + "分享了" + homeName.getName() + "给您", MessageCode.ACCOUNT_TYPE,
                child.getSourceId(), ExtrasCode.IN_SHARE, homeId, child.getId() + "",
                child.getSourceType() + "", organizationCode);

        return ControllerResult.toReturnMessageSuccess("分享成功");
    }


    /**
     * 取消分享
     *
     * @param request
     * @param homeId       取消的家庭ID
     * @param childAccount 子账号
     * @param masterOrSelf 主人或自己主动取消,0或null是主人，1是自己
     * @return
     */
    @DeleteMapping("/delChildUser")
    @CheckLogin
    public ControllerResult removeChildAccount(HttpServletRequest request, @NotBlank(message = "家庭ID不能为空") String homeId,
                                               @Phone String childAccount, String masterOrSelf) throws Exception {
        User user = (User) request.getAttribute("user");
        //组织编码
        String organizationCode = user.getOrgCode();
        if (StringUtils.isEmpty(organizationCode)) {
            organizationCode = OrgCode.ZY;
        }

        String userId = appUserService.removeChildAccount(homeId, childAccount, organizationCode);
        // 取消分享推送
        // 通过家庭id获得家庭名称
        String homeName = homeService.getHomeNameById(homeId);
        //主人取消，把消息发给对象
        if (StringUtils.isEmpty(masterOrSelf) || MASTER.equals(masterOrSelf.trim())) {
            // 推送
            AppUserDO child = appUserService.getSourceTypeByAccount(childAccount, organizationCode);
            appUserService.getSourceTypeByAccount(childAccount, organizationCode);
            jPushService.send(MessageCode.JPUSH_TITLE, homeName + "的家庭已取消分享",
                    MessageCode.ACCOUNT_TYPE, child.getSourceId(), ExtrasCode.OUT_SHARE,
                    homeId, userId, child.getSourceType() + "", organizationCode);

        }
        //自己取消，把消息发送给主人
        else if (CHILD.equals(masterOrSelf.trim())) {
            AppUserDO appUserDO = appUserService.getMasterSourceId(homeId);
            jPushService.send(MessageCode.JPUSH_TITLE, "用户" + childAccount + "已经取消了您分享的家庭：" + homeName,
                    MessageCode.ACCOUNT_TYPE, appUserDO.getSourceId(), ExtrasCode.OUT_SHARE_SELF,
                    homeId, appUserDO.getId() + "", appUserDO.getSourceType().toString(), organizationCode);
        }
        return ControllerResult.toReturnMessageSuccess("取消分享成功");


    }


    /**
     * 分享账号列表
     *
     * @param homeIdStr
     * @return
     */
    @PostMapping("/childUserList")
    @CheckLogin
    public ControllerResult getChildUserList(@NotBlank(message = "家庭ID不能为空!") @RequestParam(value = "homeId") String homeIdStr) {
        return ControllerResult.toReturnDataSuccess("获取成功", appUserService.getChildUserList(homeIdStr));
    }

    /**
     * @ClassName: AppUserController
     * @Description: 家庭转移
     * @author wjming
     * @Date 2021-05-06 13:31
     */
    @PutMapping("/transferHome")
    @CheckLogin
    @SmsCode(requestPhoneValue = "transferAccount")
    public ControllerResult familyTransfer(HttpServletRequest request,
                                           @NotBlank(message = "家庭ID不能为空!") String homeId,
                                           @NotBlank(message = "转移账号不能为空") String transferAccount) throws Exception {


        User user = (User) request.getAttribute("user");
        log.info("request -> user:[{}_{}] [familyTransfer] -> [homeId:{},transferAccount{}]", user.getAccount(), user.getOrgCode(), homeId, transferAccount);
        String organizationCode = user.getOrgCode();

        // 账号校验 自己不能给自己分享
        if (transferAccount.equals(user.getAccount())) {
            return ControllerResult.toParamFail("转移账号不能是登录账号!");
        }

        // 1.通过appUserId和HomeId之间的关系，然后修改当前homeId下的appUserId
        AppUserHomeRelationDO appUserHomeRelationDO = new AppUserHomeRelationDO();
        appUserHomeRelationDO.setAppUserId(user.getId());
        appUserHomeRelationDO.setHomeId(homeId);
        appUserService.updateAppuserId(transferAccount, appUserHomeRelationDO, organizationCode);

        // 通过家庭id获得家庭名称
        String homeName = homeService.getById(homeId).getName();

        // 通过appUserid获得昵称
        AppUserDO startUser = appUserService.getById(user.getId());

        AppUserDO child = appUserService.getSourceTypeByAccount(transferAccount, organizationCode);
        // 通过手机号获得登录的sourceId
        String sourceId = child.getSourceId();
        /** 如果昵称为空输入手机号 */
        if (startUser.getNickName() == null) {
            startUser.setNickName(startUser.getAccount());
        }
        /** 通过家庭id获得家庭对象，转成json字符串 */
        // 推送
        jPushService.send(MessageCode.JPUSH_TITLE, startUser.getNickName()
                        + "转移了" + homeName + "给您", MessageCode.ACCOUNT_TYPE,
                sourceId, ExtrasCode.IN_SHARE, "", child.getId() + "", child.getSourceType() + "", organizationCode);

        return ControllerResult.toReturnMessageSuccess("转移成功");

    }


    /**
     * 微信解绑与绑定
     *
     * @param openId 快速登陆开放平台ID
     * @param type   类型 0解绑或绑定微信，1解绑或绑定QQ 2.j解绑绑定苹果
     * @return
     */
    @PutMapping("/bindThreadAccount")
    @CheckLogin
    public ControllerResult bindThreadAccount(HttpServletRequest request, String openId,
                                              @NotBlank(message = "类型不能为空") String type) {
        User user = (User) request.getAttribute("user");
        if (StringUtils.isEmpty(openId)) {
            openId = "";
        }
        try {
            Integer typeInt = null;
            if (!StringUtils.isEmpty(type)) {
                typeInt = Integer.parseInt(type);
            }

            // openId不为空绑定 openId为空 解绑
            AppUserDO queryid = new AppUserDO();
            if (typeInt == 0) {
                queryid.setOpenidWeiXin(openId);
                queryid.setOpenidQQ(null);
                queryid.setOpenidApple(null);
            }
            if (typeInt == 1) {
                queryid.setOpenidQQ(openId);
                queryid.setOpenidWeiXin(null);
                queryid.setOpenidApple(null);
            }
            if (typeInt == APPLE) {
                queryid.setOpenidQQ(null);
                queryid.setOpenidWeiXin(null);
                queryid.setOpenidApple(openId);
            }
            queryid.setId(user.getId());

            // 如果openID都不为空的时候，清空数据库关于这个openid信息
            if (!StringUtils.isEmpty(openId)) {
                AppUserDO queryClear = new AppUserDO();

                if (typeInt == 0) {
                    queryClear.setOpenidWeiXin(openId);
                    queryClear.setOpenidQQ(null);
                    queryid.setOpenidApple(null);
                }
                if (typeInt == 1) {
                    queryClear.setOpenidQQ(openId);
                    queryClear.setOpenidWeiXin(null);
                    queryid.setOpenidApple(null);
                }
                if (typeInt == APPLE) {
                    queryid.setOpenidQQ(null);
                    queryid.setOpenidWeiXin(null);
                    queryid.setOpenidApple(openId);
                }
                appUserService.updateClearByOpenId(queryClear);
            }

            int count = appUserService.updateOpenIdById(queryid);
            if (count < 0) {
                return ControllerResult.toReturnMessageSuccess("操作异常");
            }

            if (!StringUtils.isEmpty(openId)) {
                return ControllerResult.toReturnMessageSuccess("绑定成功");
            } else {
                return ControllerResult.toReturnMessageSuccess("解绑成功");

            }

        } catch (Exception e) {
            return ControllerResult.toSysErrorFail("绑定或解绑异常");
        }

    }
}
